﻿// (c) Copyright 2013 Mike Riedel.
// This source is subject to the Microsoft Public License (Ms-PL).
// All other rights reserved.

using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;

namespace FreshMeat.Storage
{
   /// <summary>
   /// Provides XML serialization using Microsoft's <see cref="DataContractJsonSerializer"/>.
   /// </summary>
   /// <typeparam name="T"></typeparam>
   public class MsDataContractJsonSerializer<T> : ISerializer<T>, IStreamSerializer<T>
   {
      readonly DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));

      /// <summary>
      /// Serializes an object to a string.
      /// Method is thread safe.
      /// </summary>
      /// <param name="value">Item to serialize.</param>
      /// <returns>String containing the serialized data.</returns>
      public string Serialize(T value)
      {
         using (var stream = new MemoryStream())
         {
            Serialize(value, stream);
            return Encoding.UTF8.GetString(stream.ToArray(), 0, (int)stream.Length);
         }
      }

      /// <summary>
      /// Deserializes an object from a stream.
      /// Method is thread safe.
      /// </summary>
      /// <param name="data">The string containing the serialized data.</param>
      /// <returns>The deserialized object.</returns>
      public T Deserialize(string data)
      {
         using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(data)))
            return Deserialize(stream);
      }

      /// <summary>
      /// Serializes an object to a stream.
      /// Method is thread safe.
      /// </summary>
      /// <param name="item">Item to serialize.</param>
      /// <param name="output">Stream to write serialized data to.</param>
      public void Serialize(T item, Stream output)
      {
         serializer.WriteObject(output, item);
      }

      /// <summary>
      /// Deserializes an object from a stream.
      /// Method is thread safe.
      /// </summary>
      /// <param name="input">The stream to read serialized data from.</param>
      /// <returns>The deserialized object.</returns>
      public T Deserialize(Stream input)
      {
         return (T)serializer.ReadObject(input);
      }
   }
}